/*
Copyright (C) 2008 raohmaru <http://www.raohmaru.com>

This file is part of Raohmaru AS3 Framework.

Raohmaru AS3 Framework is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Raohmaru AS3 Framework is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License
along with Raohmaru AS3 Framework.  If not, see <http://www.gnu.org/licenses/>.
*/

package jp.raohmaru.managers 
{
import flash.events.*;
import flash.text.StyleSheet;
import flash.net.URLLoader;
import flash.net.URLRequest;

/**
 * Se distribuye cuando cuando los datos se han cargado correctamente.
 * @eventType flash.events.Event.COMPLETE
 */
[Event(name="complete", type="flash.events.Event") ]

/**
 * Se distribuye cuando se produce un error de entrada o salida que provoca que una operación de carga se realice incorrectamente.
 * @eventType flash.events.IOErrorEvent.IO_ERROR
 */
[Event(name="complete", type="flash.events.IOErrorEvent") ]

/**
 * La clase CSSStyleManager gestiona la carga y almacén de objetos StyleSheet, que posteriormente podrá aplicar a un objeto TextField. Al ser una clase singleton, la única instancia
 * CSSStyleManager persiste durante la ejecución de la aplicación.<br>
 * Por alguna misteriosa razón, Flash Player no renderiza los estilos aplicados a las etiquetas &lt;b&gt; y &lt;i&gt;, por lo que es mejor crear etiquetas &lt;span&gt; y definirles
 * los estilos para negrita y/o cursiva.
 * @author raohmaru
 * @version 1.0
 * @see flash.text.StyleSheet
 */
public class CSSStyleManager extends EventDispatcher
{
	private var _styles : Array = [],
				_loader : URLLoader = new URLLoader(),
				_temp_name : String;
	
	private const DEFAULT : String = "default_style";
	private static var _instance : CSSStyleManager;
	
	/**
	* Devuelve el número de hoja de estilos registradas. 
	*/
	public function get numStyleSheets() : uint
	{
		var count : uint;
		for(var i:String in _styles) 
			count++;
			
		return count;
	}
	
	
	
	/**
	 * La clase CSSStyleManager es una clase singleton, por lo que no puede ser creada a partir del constructor. Para obtener una instancia de CSSStyleManager,
	 * utilize <code>getInstance</code>.
	 * @see #getInstance()
	 */
	public function CSSStyleManager (enforcer : SingletonEnforcer)
	{
	}
	
	/**
	 * Obtiene la hoja de estilos con el nombre especificado.
	 * @param name Nombre de la hoja de estilos.
	 * @return Objeto hoja de estilos
	 * @example
	<listing version="3.0">
	import jp.raohmaru.managers.CSSStyleManager;
	import flash.text.StyleSheet;<br>
	var style : StyleSheet = new StyleSheet();
	style.setStyle("a", {textDecoration:"underline"});
	style.setStyle("a:hover", {color:"#000000"});<br>
	var cssman : CSSStyleManager = CSSStyleManager.getInstance();
	cssman.addStyle("style", style);<br>
	text_tf.styleSheet = cssman.getStyle("style");
	</listing>
	 */
	public function getStyle(name : String) : StyleSheet
	{
		return _styles[name];
	}
	
	/**
	 * Añade un nuevo objeto hoja de estilos, que se guardará con el nombre especificado. Si ya existe un objeto con ese nombre, se sobreescribirá.
	 * @param name El nombre para la hoja de estilos
	 * @param stylesheet Objeto hoja de estilos
	 * @see "Para ver un ejemplo, consulte
	 * @see #getStyle()
	 */
	public function addStyle(name : String, stylesheet : StyleSheet) : void
	{
		_styles[name] = stylesheet;
	}
	
	/**
	 * Obtiene la hoja de estilos que se ha definido por defecto en <code>setDefaultStyle</code>.
	 * @return Objeto hoja de estilos
	 * @see #getStyle()
	 * @see #setDefaultStyle()
	 */
	public function getDefaultStyle() : StyleSheet
	{
		return getStyle(DEFAULT);
	}
	
	/**
	 * Establece la hoja de estilos por defecto, que será devuelta en cada llamada a <code>getDefaultStyle</code>. Este método sobreescribe la anterior hoja de estilos.
	 * @param stylesheet Objeto hoja de estilos
	 * @see #addStyle()
	 * @see #getDefaultStyle()
	 */
	public function setDefaultStyle(stylesheet : StyleSheet) : void
	{
		addStyle(DEFAULT, stylesheet);
	}
	
	/**
	 * Elimina un objeto hoja de estilos de la lista de objetos y devuelve el objeto eliminado.
	 * @param name El nombre de la hoja de estilos a eliminar
	 * @return El objeto StyleSheet eliminado
	 */
	public function deleteStyle(name : String) : StyleSheet
	{
		var deleted : StyleSheet = _styles[name];
		delete _styles[name];
		return deleted;
	}
	
	/**
	 * Carga un archivo .css y lo añade a la lista de hojas de estilo, con el nombre especificado. Si ya existe una hojas de estilo con ese nombre, se sobreescribirá.
	 * @param name El nombre para la hoja de estilos
	 * @param url Dirección URL del archivo
	 * @example
	<listing version="3.0">
	import jp.raohmaru.managers.CSSStyleManager;<br>
	var cssman : CSSStyleManager = CSSStyleManager.getInstance();
	cssman.addEventListener(Event.COMPLETE, onLoadCSS);
	cssman.loadStyle("base", "base.css");<br> 
	function onLoadCSS(e : Event) : void
	{
		text_tf.styleSheet = cssman.getStyle("base");
	}
	</listing>
	 */
	public function loadStyle(name : String, url : String) : void
	{
		_temp_name = name;
		
        _loader.addEventListener(IOErrorEvent.IO_ERROR, loaderHandler);
        _loader.addEventListener(Event.COMPLETE, loaderHandler);
        
        _loader.load( new URLRequest(url) );
	}
	
	
	/**
	 * Carga un archivo .css y lo establece como la hoja de estilos por defecto para posteriores llamadas a <code>getDefaultStyle</code> o <code>setDefaultStyle</code>.
	 * @param url Dirección URL del archivo
	 * @see #loadStyle()
	 * @see #getDefaultStyle()
	 * @see #setDefaultStyle()
	 */
	public function loadDefaultStyle(url : String) : void
	{
		loadStyle(DEFAULT, url);
	}
	
	private function loaderHandler(e : Event) : void
	{
		if(e.type == Event.COMPLETE)
		{
			var style : StyleSheet = new StyleSheet();
				style.parseCSS(e.target.data);
			addStyle(_temp_name, style);
		}
		else
		{
			trace("Error #2032: IOError (error de secuencia). CSSStyleManager :: No se pudo cargar la hoja de estilos.");
		}
		
		_temp_name = null;
		dispatchEvent(e);
	}
	
	
	
	/**
	 * Crea una instancia singleton de CSSStyleManager para utilizar en una misma aplicación.
	 * @return Instancia singleton de CSSStyleManager
	 * @example
	<listing version="3.0">
	import jp.raohmaru.managers.CSSStyleManager;<br>
	var cssman : CSSStyleManager = CSSStyleManager.getInstance();</listing>
	 */
	public static function getInstance() : CSSStyleManager
	{
		if( _instance == null )
			_instance =	new CSSStyleManager(new SingletonEnforcer());
		
		return _instance;
	}
}
}

internal class SingletonEnforcer{} 